package cn.mxz.xmu.robots.library.utils;

import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.mxz.xmu.robots.basic.RobotsUtlis;

public final class HuiwenUtils
{
	private static final Logger LOG = LoggerFactory.getLogger(HuiwenUtils.class);

	/**
	 * 读者证信息(暂时只支持汇文)
	 * 
	 * @param readerInfoHtml
	 *            　　解析的HTML
	 * @param selector
	 *            选择器
	 * @return
	 */
	public static String readerInfoParse(String readerInfoHtml, String selector)
	{
		Document readerInfoDoc = Jsoup.parse(readerInfoHtml);

		Element trs = readerInfoDoc.select(selector).get(0);

		String textHtml = trs.select("tr td").html().replaceAll("<.*\">", "").replaceAll("</.*>", "").replace(" ", "");

		JSONObject readerInfo = new JSONObject();

		readerInfo.put("stu_id", regexMatch(textHtml, "\u8bc1\u4ef6\u53f7[:|：](.*)"));
		readerInfo.put("bar_code", regexMatch(textHtml, "\u6761\u7801\u53f7[:|：](.*)"));
		readerInfo.put("id_card", regexMatch(textHtml, "\u8eab\u4efd\u8bc1\u53f7[:|：](.*)"));
		readerInfo.put("name", regexMatch(textHtml, "\u59d3\u540d[:|：](.*)"));
		readerInfo.put("sex", regexMatch(textHtml, "\u6027\u522b[:|：](.*)"));
		readerInfo.put("issue_date", regexMatch(textHtml, "\u751f\u6548\u65e5\u671f[:|：](.*)"));
		readerInfo.put("limited_date", regexMatch(textHtml, "\u5931\u6548\u65e5\u671f[:|：](.*)"));
		readerInfo.put("company", regexMatch(textHtml, "\u5355\u4f4d[:|：](.*)"));
		readerInfo.put("address", regexMatch(textHtml, "\u4f4f\u5740[:|：](.*)"));
		readerInfo.put("telephone", regexMatch(textHtml, "\u624b\u673a\u53f7\u7801[:|：](.*)"));
		readerInfo.put("arrear", regexMatch(textHtml, "[\u6b20\u6b3e].*[:|：](.*)"));
		readerInfo.put("max_borrow", regexMatch(textHtml, "\u6700\u5927\u53ef\u501f.*[:|：](.*)"));
		readerInfo.put("total_borrow", regexMatch(textHtml, "\u7d2f\u8ba1\u501f\u4e66[:|：](\\d+)"));

		return readerInfo.toString();
	}

	/**
	 * 图书查询解析
	 * 
	 * @param queryBookHtml
	 *            图书列表解析的HTML
	 * @param selector
	 *            选择器
	 * @return 图书列表的JSONArrary
	 */
	public static String queryBooksParse(String queryBookHtml, String selector, String url)
	{
		Document queryBookDoc = Jsoup.parse(queryBookHtml);

		Elements divs = queryBookDoc.select(selector);

		JSONArray books = new JSONArray();

		for (Element els : divs)
		{
			JSONObject book = new JSONObject();

			String bookText[] = regexMatch(els.select("p").html(), "</span>(.*)<br>").split("<br>");

			System.out.println(els.select("h3 a").text());
			book.put("name", regexMatch(els.select("h3 a").text(), "(\\d+\\.)").contains(".") ? regexMatch(els.select("h3 a").text(), "\\d+\\.(.*)") : els.select("h3 a").text());
			book.put("author", bookText[0]);
			book.put("publishing", regexMatch(els.select("p").html(), "</span>.*<br>(.*)&nbsp;"));
			book.put("publish_date", regexMatch(els.select("p").html(), "&nbsp;(\\d+)"));
			book.put("index_num", regexMatch(els.select("h3").html(), "</a>(.*)"));
			book.put("num_books", regexMatch(els.text(), "\u9986\u85cf\u590d\u672c+：(\\d+)"));
			book.put("num_borrow", regexMatch(els.text(), "\u53ef\u501f\u590d\u672c：(\\d+)"));
			book.put("url", url + els.select("h3").select("a").attr("href"));

			books.add(book);
		}

		return books.toString();
	}

	/**
	 * descHtml 图书单页解析的HTML（暂只支持汇文）
	 * 
	 * @param descHtml
	 *            图书单页解析的HTML
	 * @param localJson
	 *            馆藏地图书列表信息
	 * @param appointJson
	 *            可预约图书列表信息
	 * @param paramsJson
	 *            　预约时传递的参数
	 * @return 图书单页的JSONObject
	 */
	public static String descBookParse(String descHtml, String selector, String localJson, String appointJson, String paramsJson)
	{
		Document descBookDoc = Jsoup.parse(descHtml);

		Elements eles = descBookDoc.select(selector);

		String bookinfo[] = eles.html().split("</dd>");

		StringBuilder bookStr = new StringBuilder();

		for (int i = 0; i < bookinfo.length; i++)
		{
			bookStr.append(bookinfo[i].replace(" ", "").replace("</dt>\n<dd>", "").replace("\n", "").replace("<dt>", "\n"));
		}
		String books = bookStr.toString().replaceAll("(<.*\">)", "").replaceAll("<\\/.*>", "");

		JSONObject book = new JSONObject();

		book.put("name", regexMatch(books, "[\u9898\u540d]+/.*[:|：](.*)/"));
		book.put("author", regexMatch(books, "[\u9898\u540d]+/.*[:|：].*/(.*)"));// [\u9898\u540d]+/.*[:|：].*/(.*)[\u8457|\u4e3b\u7f16]
		book.put("translator", regexMatch(books, "[\u9898\u540d]+/.*[:|：].*[\u8457](.*)[\u8bd1]"));
		book.put("type_id", regexMatch(books, "[\u5206\u7c7b\u53f7]+[:|：](.*)"));
		book.put("subject", regexMatch(books, "[\u4e3b\u9898]+[:|：](.*)"));
		book.put("version_des", regexMatch(books, "\u7248\u672c.*[:|：](.*)"));
		book.put("publishing", regexMatch(books, "[\u51fa\u7248].*[:|：](.*),"));
		book.put("publish_date", regexMatch(books, "[\u51fa\u7248].*[:|：].*,(\\d+)"));
		book.put("isbn", regexMatch(books, "ISBN.*[:|：]((\\d+-){3,4}\\d+)"));
		book.put("price", regexMatch(books, "[\u5b9a\u4ef7]+[:|：].*CNY(.*)"));
		book.put("pages", regexMatch(books, "\u5f62\u6001\u9879[:|：](.*)[\u9875]"));
		book.put("synopsis", regexMatch(books, "\u63d0\u8981\u6587\u6458.*[:|：](.*)"));
		book.put("location_info", localJson);
		book.put("apply_appoint", appointJson);
		book.put("params", paramsJson);

		return book.toString();
	}

	/**
	 * 馆藏地列表
	 * 
	 * @param parseHtml
	 *            解析的HTML
	 * @param selector
	 *            选择器
	 * @param map
	 *            　　列表信息的map
	 * @return JSONArray的字符串类型
	 */
	public static String localsParse(String parseHtml, String selector, Map<String, String> map)
	{
		if (parseHtml.contains("处理中"))
		{
			return "[]";
		}

		JSONArray locals = new JSONArray();
		try
		{
			Document localDoc = Jsoup.parse(parseHtml);
			Elements trs = localDoc.select(selector).get(0).select("tr");
			int trSize = trs.size();
			for (int i = 1; i < trSize; i++)
			{
				JSONObject local = new JSONObject();
				local.put("index_num", parseTagEles(trs, i, map.get("index_num")));
				local.put("bar_code", parseTagEles(trs, i, map.get("bar_code")));
				local.put("address", parseTagEles(trs, i, map.get("address")));
				local.put("status", parseTagEles(trs, i, map.get("status")));

				locals.add(local);
			}
		}
		catch (Exception e)
		{
			LOG.info("Library ==> Class [HuiwenUtils] method [localsParse] Exception." + e.getMessage());
		}

		return locals.toString();
	}

	/**
	 * 可预约图书列表
	 * 
	 * @param parseHtml
	 *            解析的HTML
	 * @param selector
	 *            选择器
	 * @param map
	 *            列表信息的map
	 * @return JSONArray的字符串类型　
	 */
	public static String appointsParse(String parseHtml, String selector, Map<String, String> map)
	{
		if (parseHtml.contains("id=\"err\"") || parseHtml.contains("不得预约") || parseHtml.contains("没有开放"))// 规定读者预约数为零！不得预约！
		{
			return "[]";
		}

		Document appointDoc = Jsoup.parse(parseHtml);
		JSONArray appoints = new JSONArray();

		Elements trs = appointDoc.select(selector).get(0).select("tr");
		int trSize = trs.size() - 1;// -1 表格的最后一行时执行按钮
		for (int i = 1; i < trSize; i++)
		{
			Elements tds = trs.get(i).select("td");
			int tdSize = tds.size() - 1;
			/* 只返回可以预约的图书 */
			if (!tds.get(tdSize).select("input[type=radio]").hasAttr("disabled"))
			{
				JSONObject appoint = new JSONObject();
				appoint.put("index_num", parseTagEles(trs, i, map.get("index_num")));
				appoint.put("bar_code", parseTagEles(trs, i, map.get("bar_code")));
				appoint.put("location", parseTagEles(trs, i, map.get("location")));
				appoint.put("total_borrow", parseTagEles(trs, i, map.get("total_borrow")));
				appoint.put("total_library", parseTagEles(trs, i, map.get("total_library")));
				appoint.put("get_address", parseTagEles(trs, i, map.get("get_address")));
				appoint.put("appoint_status", parseTagEles(trs, i, map.get("appoint_status")));

				appoints.add(appoint);
			}
		}

		return appoints.toString();
	}

	/**
	 * 图书预约的参数
	 * 
	 * @param parseHtml
	 * @param selector
	 *            选择器
	 * @return 字符串类型的JSONArrary
	 */
	public static String paramsParse(String parseHtml, String selector)
	{
		if (parseHtml.contains("id=\"err\"") || parseHtml.contains("不得预约") || parseHtml.contains("没有开放"))// 规定读者预约数为零！不得预约！
		{
			return "[]";
		}

		Document paramsDoc = Jsoup.parse(parseHtml);
		Elements sels = paramsDoc.select(selector).get(0).select("tr");

		JSONArray params = new JSONArray();
		int paramsSize = sels.size() - 1;// 表格的最后一行是按钮
		if (paramsSize > 0)
		{
			JSONObject param = new JSONObject();

			Map<String, String> map = new LinkedHashMap<String, String>();

			for (int i = 1; i < paramsSize; i++)
			{
				Elements tds = sels.get(i).select("td");
				int tdSize = tds.size() - 1;

				param.put("callno" + i, tds.select("input[name=callno" + i + "]").val());
				param.put("location" + i, tds.select("input[name=location" + i + "]").val());
				param.put("pregKeepDays" + i, tds.select("input[name=pregKeepDays" + i + "]").val());

				if (!tds.get(tdSize).select("input[type=radio]").hasAttr("disabled"))
				{
					param.put("preg_days" + i, tds.select("input[name=preg_days" + i + "]").val());
					param.put("take_loca" + i, tds.select("select[name=take_loca" + i + "] option").get(0).val());

					map.put("check" + i, tds.select("input[name=check]").val());
				}
			}

			if (map.size() > 0)
			{
				Iterator<Entry<String, String>> iter = map.entrySet().iterator();
				while (iter.hasNext())
				{
					Entry<String, String> entry = (Entry<String, String>) iter.next();
					param.put("marc_no", paramsDoc.select("input[name=marc_no]").val());
					param.put("count", paramsDoc.select("input[name=count]").val());
					param.put("check", entry.getValue());
					params.add(param);
				}
			}
		}

		return params.toString();
	}

	/**
	 * 当前借阅
	 * 
	 * @param currentHtml
	 *            当前借阅解析html
	 * @param selector
	 *            选择器
	 * @param map
	 * @return 字符串类型的JSONArrary
	 */
	public static String currentBorrowParse(String currentHtml, String selector, Map<String, String> map)
	{
		if (currentHtml.contains("记录为空"))
		{
			return "[]";
		}
		Document borrowCurDoc = Jsoup.parse(currentHtml);

		Elements trs = borrowCurDoc.select(selector).get(0).select("tr");

		JSONArray currents = new JSONArray();
		int trSize = trs.size();
		for (int i = 1; i < trSize; i++)
		{
			/* 续借参数 */
			JSONObject param = new JSONObject();

			// 页面js function的格式
			String paramKey[] = regexMatch(currentHtml, "function\\sgetInLib\\((.*)\\)").split(",");
			String paramsVal = regexMatch(trs.select("input[type=button]").attr("onclick"), "\\((.*)\\)").replace("'", "");
			String pText[] = paramsVal.split(",");

			int paramKeySize = paramKey.length - 1;
			for (int j = 0; j < paramKeySize; j++)
			{
				paramKey[j] = paramKey[j].contains("barcode") ? "bar_code" : paramKey[j];
				param.put(paramKey[j], pText[j]);
			}

			/* 借阅列表 */
			JSONObject current = new JSONObject();
			current.put("index_num", parseTagEles(trs, i, map.get("index_num")));
			current.put("bar_code", parseTagEles(trs, i, map.get("bar_code")));
			current.put("name", parseTagEles(trs, i, map.get("name")));
			current.put("author", parseTagEles(trs, i, map.get("author")));
			current.put("translator", parseTagEles(trs, i, map.get("translator")));
			current.put("borrow_date", parseTagEles(trs, i, map.get("borrow_date")));
			current.put("return_date", parseTagEles(trs, i, map.get("return_date")));
			current.put("location_addr", parseTagEles(trs, i, map.get("location_addr")));
			current.put("params", param.toString());

			currents.add(current);
		}

		return currents.toString();
	}

	/**
	 * 我预约的图书　解析
	 * 
	 * @param currentHtml
	 *            我预约的图书　解析的html
	 * @param selector
	 *            选择器
	 * @param map
	 * @return 字符串类型的JSONArrary
	 */
	public static String myAppointsParse(String appointsHtml, String selector, Map<String, String> map)
	{
		if (appointsHtml.contains("记录为空"))
		{
			return "[]";
		}
		Document myAppointsDoc = Jsoup.parse(appointsHtml);

		Elements trs = myAppointsDoc.select(selector).get(0).select("tr");

		JSONArray appoints = new JSONArray();
		int trSize = trs.size();
		for (int i = 1; i < trSize; i++)
		{
			/* 取消预约参数 */
			JSONObject param = new JSONObject();
			String paramsText = regexMatch(trs.select("input[type=button]").attr("onclick"), "\\((.*)\\)").replace("'", "");
			String pText[] = paramsText.split(",");
			param.put("call_no", pText[1]);
			param.put("marc_no", pText[0]);
			param.put("loca", pText[3]);

			/* 我预约的图书列表 */
			JSONObject appoint = new JSONObject();
			appoint.put("index_num", parseTagEles(trs, i, map.get("index_num")));
			appoint.put("bar_code", parseTagEles(trs, i, map.get("bar_code")));
			appoint.put("name", parseTagEles(trs, i, map.get("name")));
			appoint.put("author", parseTagEles(trs, i, map.get("author")));
			appoint.put("translator", parseTagEles(trs, i, map.get("translator")));
			appoint.put("location", parseTagEles(trs, i, map.get("location")));
			appoint.put("get_address", parseTagEles(trs, i, map.get("get_address")));
			appoint.put("begin_date", parseTagEles(trs, i, map.get("begin_date")));
			appoint.put("end_date", parseTagEles(trs, i, map.get("end_date")));
			appoint.put("state", parseTagEles(trs, i, map.get("state")));
			appoint.put("params", param.toString());

			appoints.add(appoint);
		}

		return appoints.toString();
	}

	/**
	 * 解析Elements
	 * 
	 * @param elements
	 * @param begeinTr
	 * @param endTd
	 * @return
	 */
	private static String parseTagEles(Elements elements, int begeinTr, String endTd)
	{
		String returnVal = "";

		if (!"".equals(endTd))
		{
			try
			{
				/* text field */
				if (!endTd.contains("@"))
				{
					if (!endTd.contains("_"))
					{
						returnVal = elements.get(begeinTr).select("td").get(Integer.parseInt(endTd)).text();
					}
					/* split "_" 后见面是正则表达式 */
					else
					{
						String regx[] = endTd.split("_");
						String regxPattern = regx[regx.length - 1];
						String resource = elements.get(begeinTr).select("td").get(Integer.parseInt(regx[0])).text();
						returnVal = regexMatch(resource, regxPattern);
					}
				}
				/* select field */
				else
				{
					String regx[] = endTd.split("@");
					String regxPattern = regx[regx.length - 1];

					Element resELe = elements.get(begeinTr).select("td").get(Integer.parseInt(regx[0]));

					/* 禁用的select field */
					if (resELe.html().contains("disabled"))
					{
						returnVal = resELe.select("select[name=" + regxPattern + "] option").get(0).text();
					}
					else
					{
						regxPattern = regxPattern + begeinTr;
						returnVal = resELe.select("select[name=" + regxPattern + "] option").get(0).text();
					}
				}
			}
			catch (Exception e)
			{
				LOG.error("Library ==> class [HuiwenUtils] method [parseTagEles] Exception." + e.getMessage());
				returnVal = "";
			}
		}

		return returnVal;
	}

	/**
	 * 把JSONObject 转换为url的格式
	 * 
	 * @param params
	 * @return
	 */
	@SuppressWarnings("rawtypes")
	public static String urlSerialization(String params)
	{

		JSONObject paramsObj = JSONObject.fromObject(params);
		String urlParams = "";
		for (Iterator iter = paramsObj.keys(); iter.hasNext();)
		{
			String key = (String) iter.next();
			String value = paramsObj.getString(key);
			urlParams += key + "=" + value + "&";
		}

		return urlParams.substring(0, urlParams.length() - 1);
	}

	/**
	 * 把selector选择的doc转化为 <code>JSONArray.toString()</code>
	 * 
	 * @param docHtml
	 *            文档对象
	 * @param i
	 *            int 类型的参数，代表for循环的初始值,从下标几开始循环　
	 * @param selector
	 *            父选择器，选择的信息，遵循Jsoup选择器格式
	 * @param subSelector
	 *            子选择器，选择的信息，遵循Jsoup选择器格式
	 * @param map
	 *            需要转换的数据
	 * @return 字符串格式的JSONArrary
	 */
	public static String parseJSONDoc(String docHtml, int i, String selector, String subSelector, Map<String, String> map)
	{

		String retunJson = "";

		Document doc = Jsoup.parse(docHtml);
		Elements eles = doc.select(selector);
		if (!selector.equals(""))
		{
			JSONArray jsons = new JSONArray();

			int elesSize = eles.size();
			for (; i < elesSize; i++)
			{
				Elements subEles = eles.get(i).select(subSelector);
				jsons.add(parseMapConvertJSON(subEles, map));
			}

			return retunJson = jsons.toString();
		}
		else
		{
			retunJson = parseMapConvertJSON(eles, map).toString();
		}

		return retunJson;
	}

	/**
	 * 根据 Elements 解析map 为JSONObject
	 * 
	 * @param eles
	 * @param map
	 * @return
	 */
	public static JSONObject parseMapConvertJSON(Elements eles, Map<String, String> map)
	{

		JSONObject json = new JSONObject();
		if (map.size() > 0)
		{
			Iterator<?> iter = map.entrySet().iterator();
			while (iter.hasNext())
			{
				Entry<?, ?> entry = (Entry<?, ?>) iter.next();
				String value = entry.getValue().toString();
				String tagVal = parseSelectorTag(eles, value);
				json.put(entry.getKey(), tagVal);
			}
		}
		return json;
	}

	/**
	 * @param index
	 *            或 index_regex
	 * 
	 *            index ：元素所在的下标
	 *            regex ：正则表达式
	 * @param eles
	 * 
	 * @return
	 */
	private static String parseSelectorTag(Elements eles, String index)
	{

		String returnVal = "";
		if (!index.equals(""))
		{
			if (index.contains("_"))
			{
				String args[] = index.split("_");
				String oldVal = eles.get(Integer.parseInt(args[0])).text();
				returnVal = regexMatch(oldVal, args[1]);
			}
			else
			{
				returnVal = eles.get(Integer.parseInt(index)).text();
			}
		}

		return returnVal;
	}

	/**
	 * 解析图书单页(汇文系统)
	 * 
	 * @param args
	 * @param locations
	 * @param applyAppoint
	 * @param params
	 * @return
	 */
	public static String parseDescBook(String args[], String locations, String applyAppoint, String params)
	{

		StringBuilder bookStr = new StringBuilder();
		for (int i = 0; i < args.length; i++)
		{
			bookStr.append(args[i].replace(" ", "").replace("</dt>\n<dd>", "").replace("\n", "").replace("<dt>", "\n"));
		}
		String books = bookStr.toString().replaceAll("(<.*\">)", "").replaceAll("<\\/.*>", "");

		JSONObject book = new JSONObject();

		book.put("name", regexMatch(books, "[\u9898\u540d]+/.*[:|：](.*)/"));
		book.put("author", regexMatch(books, "[\u9898\u540d]+/.*[:|：].*/(.*)[\u8457]"));
		book.put("translator", regexMatch(books, "[\u9898\u540d]+/.*[:|：].*[\u8457](.*)[\u8bd1]"));
		book.put("type_id", regexMatch(books, "[\u5206\u7c7b\u53f7]+[:|：](.*)"));
		book.put("subject", regexMatch(books, "[\u4e3b\u9898]+[:|：](.*)"));
		book.put("version_des", regexMatch(books, "\u7248\u672c.*[:|：](.*)"));
		book.put("publishing", regexMatch(books, "[\u51fa\u7248].*[:|：](.*),"));
		book.put("publish_date", regexMatch(books, "[\u51fa\u7248].*[:|：].*,(\\d+)"));
		book.put("isbn", regexMatch(books, "ISBN.*[:|：]((\\d+-){3,4}\\d+)"));
		book.put("price", regexMatch(books, "[\u5b9a\u4ef7]+[:|：].*CNY(.*)"));
		book.put("pages", regexMatch(books, "[:|：](\\d+)[\u9875]"));
		book.put("synopsis", regexMatch(books, "\u63d0\u8981\u6587\u6458.*[:|：](.*)"));
		book.put("location_info", locations);
		book.put("apply_appoint", applyAppoint);
		book.put("params", params);

		return book.toString();
	}

	private static String regexMatch(String str, String regex)
	{
		return RobotsUtlis.regexMatch(str, regex);
	}

}
